package com.xhwl.logistics.service.logistics.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.logistics.converter.mapstruct.logistics.ApprovalNodeConverter;
import com.xhwl.logistics.converter.mapstruct.logistics.ApprovalProgressConvert;
import com.xhwl.logistics.converter.mapstruct.logistics.VisitorRecordConverter;
import com.xhwl.logistics.dto.CardInfoDTO;
import com.xhwl.logistics.entity.approval.ApprovalNode;
import com.xhwl.logistics.entity.approval.ApprovalProcess;
import com.xhwl.logistics.entity.approval.ApprovalProgress;
import com.xhwl.logistics.entity.logistics.VisitorRecord;
import com.xhwl.logistics.dao.mapper.logistics.VisitorRecordMapper;
import com.xhwl.logistics.enums.logistics.ApprovalProcessDelEnum;
import com.xhwl.logistics.enums.logistics.ApprovalProcessTypeEnum;
import com.xhwl.logistics.enums.logistics.ApprovalProgressStatusEnum;
import com.xhwl.logistics.enums.logistics.ApprovalStatusEnum;
import com.xhwl.logistics.logistics.request.ApprovalParam;
import com.xhwl.logistics.logistics.request.VisitorRecordRequestParam;
import com.xhwl.logistics.query.ApprovalQuery;
import com.xhwl.logistics.query.VisitorRecordQuery;
import com.xhwl.logistics.service.logistics.IApprovalNodeService;
import com.xhwl.logistics.service.logistics.IApprovalProcessService;
import com.xhwl.logistics.service.logistics.IApprovalProgressService;
import com.xhwl.logistics.service.logistics.IVisitorRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhwl.logistics.util.PageResult;
import com.xhwl.logistics.util.PageResultUtils;
import com.xhwl.logistics.vo.logistics.VisitorRecordVO;
import com.xhwl.logistics.vo.logistics.approval.ApprovalNodeVO;
import com.xhwl.logistics.vo.logistics.approval.ApprovalProcessVO;
import com.xhwl.logistics.vo.logistics.approval.ApprovalProgressVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 物流车预约 服务实现类
 * </p>
 *
 * @author lin.yang
 * @since 2023-12-06
 */
@Service
@Slf4j
public class VisitorRecordServiceImpl extends ServiceImpl<VisitorRecordMapper, VisitorRecord> implements IVisitorRecordService {

    @Autowired
    private VisitorRecordMapper visitorRecordMapper;


    @Autowired
    private IApprovalProgressService approvalProgressService;

    @Autowired
    private IApprovalProcessService processService;

    @Autowired
    private IApprovalNodeService approvalNodeService;


    /**
     * 获取物流车预约列表或者详情信息
     *
     * @param query
     * @return
     */
    @Override
    public ResultJson<List<VisitorRecordVO>> queryVisitorRecord(VisitorRecordQuery query) {
        log.info("queryVisitorRecord() called with parameters => 【query = {}】", query);
        List<VisitorRecord> list = Optional.ofNullable(visitorRecordMapper.queryVisitorRecord(query))
                .orElse(Collections.emptyList());
        if (list.size() > 0) {
            //po转vo
            List<VisitorRecordVO> visitorRecordVOS = VisitorRecordConverter.INSTANCE.toVoConvertList(list);
            for (VisitorRecordVO visitorRecordVO : visitorRecordVOS) {
                visitorRecordVO.setStatusText(
                        Arrays.stream(ApprovalStatusEnum.values()).filter(x -> x.getCode().equals(visitorRecordVO.getStatus())).map(x -> x.getLabel()).findFirst().orElse(null)
                );
            }
            return ResultJson.success(visitorRecordVOS);
        }
        return ResultJson.success(Collections.emptyList());
    }

    @Override
    public ResultJson saveOrUpdateVisitorRecord(VisitorRecordRequestParam params) {
        log.info("saveOrUpdateVisitorRecord() called with parameters => 【params = {}】", params);
        String idCard = Optional.ofNullable(params).map(x -> x.getIdCard()).orElse(null);
        if (ObjectUtil.isNotNull(idCard)) {
            //同样的时间段是否有进行中的预约
            LambdaQueryWrapper<VisitorRecord> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(VisitorRecord::getIdCard, idCard);
            queryWrapper.eq(VisitorRecord::getDriverName, params.getDriverName());
            //待审批和已通过的
            queryWrapper.in(VisitorRecord::getStatus, ApprovalStatusEnum.WAITING_APPROVAL.getCode(),ApprovalStatusEnum.PASS_APPROVAL.getCode());
            List<VisitorRecord> list = this.list(queryWrapper);
            if (list.size()>0) {
                //有着预约中的物流预约
                for (VisitorRecord visitorRecord : list) {
                    if (DateUtil.isIn(params.getAvailableStartDate(),visitorRecord.getAvailableStartDate(),visitorRecord.getAvailableEndDate())
                            ||DateUtil.isIn(params.getAvailableEndDate(),visitorRecord.getAvailableStartDate(),visitorRecord.getAvailableEndDate())) {
                        //如果重新预约的时间在区间内
                        return ResultJson.fail("存在进行中的预约");
                    }
                }

            }

        }
        VisitorRecord po = new VisitorRecord();
        if (ObjectUtil.isNull(Optional.ofNullable(params).map(x -> x.getStatus()).orElse(null))) {
            //默认为待审批状态
            params.setStatus(ApprovalStatusEnum.WAITING_APPROVAL.getCode());
        }

        BeanUtils.copyProperties(params, po);
        po.setOperateDate(new Date());
        if (Optional.ofNullable(params).map(x -> x.getFaceUrl()).orElse(Collections.emptyList()).size() > 0) {
            po.setFaceUrl(params.getFaceUrl().stream().collect(Collectors.joining(",")));
        }
        if (Optional.ofNullable(params).map(x -> x.getMaterialPicUrl()).orElse(Collections.emptyList()).size() > 0) {
            po.setMaterialPicUrl(params.getMaterialPicUrl().stream().collect(Collectors.joining(",")));
        }
        this.saveOrUpdate(po);
        Integer id = po.getId();
        //保存审批流程进度
        LambdaQueryWrapper<ApprovalProcess> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ApprovalProcess::getProcessType, ApprovalProcessTypeEnum.Logistics.getCode());
        queryWrapper.eq(ApprovalProcess::getLogicDel, ApprovalProcessDelEnum.IS_ENABLE.getCode());
        List<ApprovalProcess> list = Optional.ofNullable(processService.list(queryWrapper)).orElse(Collections.emptyList());
        //获取物流流程
        String flowId=null;
        if (list.size() > 0) {
            //存在对应的物流流程
            //绑定流程流程id
            ApprovalQuery approvalQuery = new ApprovalQuery();
            //获取流程详情
            approvalQuery.setProcessId(list.get(0).getProcessId());
            po.setFlowId(list.get(0).getProcessId());
            po.setFlowName(list.get(0).getProcessName());
            this.saveOrUpdate(po);
            ApprovalProcessVO approvalProcessVO = Optional.ofNullable(this.processService.detailApprovalInfo(approvalQuery)).map(x -> x.getResult()).orElse(null);
            //对应的流程由多少个节点信息list
            for (int i = 0; i < approvalProcessVO.getApprovalNodeList().size(); i++) {
                ApprovalNodeVO approvalNodeVO = approvalProcessVO.getApprovalNodeList().get(i);
                ApprovalProgress progress = new ApprovalProgress();
                //绑定业务id
                progress.setBusinessId(String.valueOf(id));
                progress.setProcessId(approvalProcessVO.getProcessId());
                //默认设置为第一个节点
                progress.setCurrentNodeId(approvalNodeVO.getNodeId());
                progress.setCreatedTime(new Date());
                progress.setProcessStatus(0==i?ApprovalProgressStatusEnum.PROGRESSING.getCode():ApprovalProgressStatusEnum.NOT_START.getCode());
                progress.setProcessType(approvalProcessVO.getProcessType());
                approvalProgressService.saveOrUpdate(progress);
            }
        }
        //开始处理走预约流程
        return ResultJson.success();
    }


    /**
     * 物流车记录详情
     *
     * @param query
     * @return
     */
    @Override
    public ResultJson<VisitorRecordVO> detailVisitorRecord(VisitorRecordQuery query) {
        log.info("detailVisitorRecord() called with parameters => 【query = {}】", query);
        VisitorRecord visitorRecord = Optional.ofNullable(this.getBaseMapper().selectById(query.getId())).orElse(null);
        if (ObjectUtil.isNull(visitorRecord)) {
            throw new BusinessException("查无此数据记录");
        }
        //已过期为优先级
        if (DateUtil.compare(DateUtil.date(),visitorRecord.getAvailableEndDate())>0) {
            //过期无效
            visitorRecord.setStatus(ApprovalStatusEnum.EXPIRE_APPROVAL.getCode());
        }
        VisitorRecordVO vo = VisitorRecordConverter.INSTANCE.toVoConvert(visitorRecord);
        if (ObjectUtil.isNotNull(visitorRecord.getFaceUrl())) {
            String[] split = visitorRecord.getFaceUrl().split(",");
            vo.setFaceUrl(Arrays.asList(split));
        }
        if (ObjectUtil.isNotNull(visitorRecord.getMaterialPicUrl())) {
            String[] split = visitorRecord.getMaterialPicUrl().split(",");
            vo.setMaterialPicUrl(Arrays.asList(split));
        }
        //设置审批状态中文值
        vo.setStatusText(
                Arrays.stream(ApprovalStatusEnum.values()).filter(x -> x.getCode().equals(vo.getStatus())).map(x -> x.getLabel()).findFirst().orElse(null)
        );

        ApprovalQuery approvalQuery = new ApprovalQuery();
        //该业务对应流程id
        approvalQuery.setProcessId(vo.getFlowId());
        ApprovalProcessVO approvalProcessVO = Optional.ofNullable(this.processService.detailApprovalInfo(approvalQuery)).map(x -> x.getResult()).orElse(null);
        if (ObjectUtil.isNotNull(approvalProcessVO)) {
            vo.setApprovalProcessVO(approvalProcessVO);
            //当前业务id
            Integer currentBusinessId = vo.getId();
            LambdaQueryWrapper<ApprovalProgress> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(ApprovalProgress::getBusinessId,String.valueOf(currentBusinessId));
            //获取进度信息
            List<ApprovalProgress> progressList = this.approvalProgressService.list(queryWrapper);
            List<ApprovalProgressVO> approvalProgressVOS = ApprovalProgressConvert.INSTANCE.toVoConvertList(progressList);
            for (ApprovalProgressVO approvalProgressVO : approvalProgressVOS) {
                //找到所属节点信息
                String currentNodeId = approvalProgressVO.getCurrentNodeId();
                ApprovalNode node = this.approvalNodeService.getById(currentNodeId);
                approvalProgressVO.setApprovalNodeVO(ApprovalNodeConverter.INSTANCE.toVoConvert(node));
            }
            vo.setCurrentProgressList(approvalProgressVOS);
        }
        return ResultJson.success(vo);
    }


    /**
     * 审批通过或者驳回拒绝
     * @param params
     * @return
     */
    @Override
    @Transactional
    public ResultJson approvalVisitorRecordRequest(ApprovalParam params) {
        log.info("approvalVisitorRecordRequest() called with parameters => 【params = {}】",params);
        //获取对应的物流车预约的id
        Integer id = Optional.ofNullable(params).map(x -> x.getId()).orElse(null);
        //传递过来的状态为通过则通过，驳回则为驳回
        Integer status = Optional.ofNullable(params).map(x -> x.getStatus()).orElse(null);
        VisitorRecordQuery visitorRecordQuery = new VisitorRecordQuery();
        visitorRecordQuery.setId(id);
        //获取该物流车详情信息
        VisitorRecordVO visitorRecordVO = Optional.ofNullable(this.detailVisitorRecord(visitorRecordQuery)).map(x -> x.getResult()).orElse(null);
        List<ApprovalProgressVO> progressList = Optional.ofNullable(visitorRecordVO.getCurrentProgressList()).orElse(Collections.emptyList());
        if (progressList.size()>0) {
            //找到进行中的进度
            ApprovalProgress approvalProgress = progressList.stream().filter(x -> x.getProcessStatus() == ApprovalProgressStatusEnum.PROGRESSING.getCode())
                    .findFirst().orElse(null);
            //可能会没有进行中的节点信息
            if (ObjectUtil.isNull(approvalProgress)&&params.getStatus().equals(ApprovalStatusEnum.CANCEL.getCode())) {
                //没有进行中的节点取消预约的情况
                VisitorRecord visitorRecord = VisitorRecordConverter.INSTANCE.toPoConvert(visitorRecordVO);
                visitorRecord.setStatus(ApprovalStatusEnum.CANCEL.getCode());
                this.saveOrUpdate(visitorRecord);
                return ResultJson.success();
            }

            approvalProgress.setProcessStatus(params.getStatus());
            if (ObjectUtil.isNotNull(params.getApprovalUserName())) {
                approvalProgress.setApprovalUser(params.getApprovalUserName());
            }
            if (ObjectUtil.isNotNull(params.getApprovalId())) {
                approvalProgress.setApprovalId(params.getApprovalId());
            }
            //节点对应的审批意见描述信息
            approvalProgress.setApprovalDesc(params.getDescription());
            approvalProgress.setApprovalDate(new Date());
            this.approvalProgressService.saveOrUpdate(approvalProgress);
            if (status== ApprovalProgressStatusEnum.PASS.getCode()) {
                //如果是通过
                int index = progressList.indexOf(approvalProgress);
                //判断是否到了最后一个进度节点
                if (progressList.size()==(index+1)) {
                    //到了最后一个进度节点
                    VisitorRecord visitorRecord = VisitorRecordConverter.INSTANCE.toPoConvert(visitorRecordVO);
                    //已经通过整个业务流程全部通过
                    visitorRecord.setStatus(ApprovalStatusEnum.PASS_APPROVAL.getCode());
                    visitorRecord.setApprovalDate(new Date());
                    this.saveOrUpdate(visitorRecord);
                }else{
                    //没有到达最后一个进度节点
                    ApprovalProgress nextApprovalProgress = progressList.get(index + 1);
                    nextApprovalProgress.setProcessStatus(ApprovalProgressStatusEnum.PROGRESSING.getCode());
                    this.approvalProgressService.saveOrUpdate(nextApprovalProgress);
                }
            }else if(status==ApprovalProgressStatusEnum.REJECT.getCode()){
                //驳回 拒绝操作  只要有一个驳回直接全部退回需要重新申请
                this.approvalProgressService.saveOrUpdate(approvalProgress);
                VisitorRecord visitorRecord = VisitorRecordConverter.INSTANCE.toPoConvert(visitorRecordVO);
                visitorRecord.setStatus(ApprovalStatusEnum.REJECT_APPROVAL.getCode());
                this.saveOrUpdate(visitorRecord);
            }
        }
        //取消
        VisitorRecord visitorRecord = VisitorRecordConverter.INSTANCE.toPoConvert(visitorRecordVO);
        if (status== ApprovalStatusEnum.CANCEL.getCode()) {
            //取消
            visitorRecord.setStatus(ApprovalStatusEnum.CANCEL.getCode());
            this.saveOrUpdate(visitorRecord);
            //ApprovalProcessVO approvalProcessVO = visitorRecordVO.getApprovalProcessVO();
            //对应的进度全部为结束状态
            for (ApprovalProgress approvalProgress : visitorRecordVO.getCurrentProgressList()) {
                approvalProgress.setProcessStatus(ApprovalProgressStatusEnum.END.getCode());
                this.approvalProgressService.saveOrUpdate(approvalProgress);
            }
        }
        return ResultJson.success();
    }

    /**
     * 分页显示物流车预约记录列表
     *
     * @param query
     * @return
     */
    @Override
    public ResultJson<PageResult<VisitorRecordVO>> pageVisitorRecordRequest(VisitorRecordQuery query) {
        log.info("pageVisitorRecordRequest() called with parameters => 【query = {}】", query);
        Page<VisitorRecord> visitorRecordPage = this.visitorRecordMapper.pageVisitorRecordRequest(query, PageResultUtils.getMyBatisPlusPage(query));
        List<VisitorRecordVO> voList = new ArrayList<>();
        for (VisitorRecord record : visitorRecordPage.getRecords()) {
            Date availableStartDate = record.getAvailableStartDate();
            Date availableEndDate = record.getAvailableEndDate();
            if (DateUtil.compare(DateUtil.date(), availableEndDate)>0) {
                //过期
                record.setStatus(ApprovalStatusEnum.EXPIRE_APPROVAL.getCode());
                this.saveOrUpdate(record);
            }
            VisitorRecordVO visitorRecordVO = VisitorRecordConverter.INSTANCE.toVoConvert(record);
            if (ObjectUtil.isNotNull(record.getFaceUrl())) {
                String[] split = record.getFaceUrl().split(",");
                visitorRecordVO.setFaceUrl(Arrays.asList(split));
            }
            if (ObjectUtil.isNotNull(record.getMaterialPicUrl())) {
                String[] split = record.getMaterialPicUrl().split(",");
                visitorRecordVO.setMaterialPicUrl(Arrays.asList(split));
            }
            visitorRecordVO.setStatusText(
                    Arrays.stream(ApprovalStatusEnum.values()).filter(x -> x.getCode().equals(record.getStatus())).map(x -> x.getLabel()).findFirst().orElse("")
            );
            voList.add(visitorRecordVO);
        }
        return ResultJson.success(PageResultUtils.getPageResult(visitorRecordPage, voList));
    }
}
